﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;

namespace ExifTool
{
    /*PropertyItem 中对应属性
     * ID	Property tag
       0x0000	PropertyTagGpsVer
       0x0001	PropertyTagGpsLatitudeRef
       0x0002	PropertyTagGpsLatitude
       0x0003	PropertyTagGpsLongitudeRef
       0x0004	PropertyTagGpsLongitude
       0x0005	PropertyTagGpsAltitudeRef
       0x0006	PropertyTagGpsAltitude
     */

    /// <summary>
    /// 删除图像的经纬度信息
    /// </summary>
    public class ExifUtil
    {
        /// <summary>
        /// 删除图像的经纬度信息，覆盖原图像
        /// </summary>
        /// <param name="IN_File">文件路径</param>
        public void DeleteCoord(string IN_File)
        {
            using (Stream ms = new MemoryStream(File.ReadAllBytes(IN_File)))
            {
                using (Image image = Image.FromStream(ms))
                {
                    DeleteCoordInfo(image);
                    image.Save(IN_File);
                }
            }
        }

        
        /// <summary>
        /// 删除图像的经纬度信息,并另存为
        /// </summary>
        /// <param name="IN_File">文件路径</param>
        public void DeleteCoord(string IN_File, string IN_Save)
        {
            using (Stream ms = new MemoryStream(File.ReadAllBytes(IN_File)))
            {
                using (Image image = Image.FromStream(ms))
                {
                    DeleteCoordInfo(image);
                    image.Save(IN_Save);
                }
            }
        }
        /// <summary>
        /// 删除图像的经纬度信息
        /// </summary>
        /// <param name="image"></param>
        public static void DeleteCoordInfo(Image image)
        {
            int[] ids = new[] { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006 };
            foreach (int id in ids)
            {
                if (image.PropertyIdList.Contains(id))
                {
                    image.RemovePropertyItem(id);
                }
            }
        }

        /// <summary>
        ///  适用范围（中国境内）
        /// </summary>
        /// <param name="imgPath"></param>
        /// <param name="lon"></param>
        /// <param name="lat"></param>
        /// <param name="alt"></param>
        /// <param name="saveAs"></param>
        public static void WriteCoord(string imgPath,double lon, double lat,double alt,string saveAs = null)
        {
            lon = Math.Round(lon, 5);
            lat = Math.Round(lat, 5);
            alt = Math.Round(alt,5);
            byte[] fileBytes;
            using (FileStream stream = new FileStream(imgPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                int byteLength = (int)stream.Length;
                fileBytes = new byte[byteLength];
                stream.Read(fileBytes, 0, byteLength);
            }
            using (Image img = Image.FromStream(new MemoryStream(fileBytes)))
            {
                //取得所有的属性(以PropertyId做排序)
                var propertyItems = img.PropertyItems.OrderBy(x => x.Id).ToArray();
                int id = img.PropertyIdList[0];
                //经纬度版本  
                PropertyItem gpsItem = img.GetPropertyItem(id);

                gpsItem.Id = 0x0000;
                gpsItem.Len = 4;
                gpsItem.Type = 1;
                gpsItem.Value = new byte[] { 2, 3, 0, 0 };
                img.SetPropertyItem(gpsItem);

                //纬度符号
                PropertyItem latRefItem = img.GetPropertyItem(id);

                latRefItem.Id = 0x0001;
                latRefItem.Len = 2;
                latRefItem.Type = 2;
                latRefItem.Value = BitConverter.GetBytes('N');
                img.SetPropertyItem(latRefItem);

                // 纬度 id 0x0002 type = 5 ;len = 24
                PropertyItem latItem = img.GetPropertyItem(id);

                latItem.Id = 0x0002;
                latItem.Len = 24;
                latItem.Type = 5;
               
                latItem.Value = GetLonLatBytes(lat);
                img.SetPropertyItem(latItem);


                //经度符号 3 2 2
                PropertyItem lonRefItem = img.GetPropertyItem(id);

                lonRefItem.Id = 0x0003;
                lonRefItem.Len = 2;
                lonRefItem.Type = 2;
                lonRefItem.Value = BitConverter.GetBytes('E');
                img.SetPropertyItem(lonRefItem);

                // 经度 0x0004 
                PropertyItem lonItem = img.GetPropertyItem(id);

                lonItem.Id = 0x0004;
                lonItem.Len = 24;
                lonItem.Type = 5;
                //string strLon = TostrLat(lon);
                lonItem.Value = GetLonLatBytes(lon);
                img.SetPropertyItem(lonItem);


                // 5 1 1 
                PropertyItem altRefItem = img.GetPropertyItem(id);
                altRefItem.Id = 0x0005;
                altRefItem.Len = 1;
                altRefItem.Type = 1;
                altRefItem.Value = new Byte[] { 0 };
                img.SetPropertyItem(altRefItem);



                //6 8 5 
                PropertyItem altItem = img.GetPropertyItem(id);
                altItem.Id = 0x0006;
                altItem.Len = 8;
                altItem.Type = 5;
                altItem.Value = GetRational3Bytes(alt);
                img.SetPropertyItem(altItem);

                if (string.IsNullOrEmpty(saveAs)||string.IsNullOrWhiteSpace(saveAs))
                {
                    img.Save(imgPath);
                }
                else
                {
                    img.Save(saveAs);
                }
            }
        }


        private static byte[] GetRational3Bytes(double alt)
        {
            //保留小数点后三位
            var fenziByte = BitConverter.GetBytes((int)(alt * 1000));//分子
            var fenmuByte = BitConverter.GetBytes(1000);//分母
        

            List<byte> re = new List<byte>();
            re.AddRange(fenziByte);
            re.AddRange(fenmuByte);
            return re.ToArray();
        }

        /// <summary>
        /// 将经纬度转为比特
        /// </summary>
        /// <param name="lonLat"></param>
        /// <returns></returns>
        private static byte[] GetLonLatBytes(double lonLat)
        {
            int du = (int)lonLat;//度

            double fenD = lonLat - du;
            int fen = (int)((fenD) * 60);//分

            double miaoD = fenD - fen / 60D;
            double miao = (miaoD * 3600);//秒


         
            var duByte1 = BitConverter.GetBytes(du);//度 分子部分比特
            var bytes = BitConverter.GetBytes(1);

         
            var fenByte1 = BitConverter.GetBytes(fen);//分 分子部分比特

            var miaoBytes = GetRational3Bytes(miao);


            List<byte> re = new List<byte>();
            re.AddRange(duByte1);
            re.AddRange(bytes);

            re.AddRange(fenByte1);
            re.AddRange(bytes);

            re.AddRange(miaoBytes);
            re.AddRange(bytes);


            return re.ToArray();
        }

    }


   
}
